from datetime import datetime
from typing import List, Optional
from sqlmodel import Field, Relationship, SQLModel, func
from pydantic import EmailStr, BaseModel


class UserBase(SQLModel):
    avatar: str = Field(default="")
    email: EmailStr = Field(unique=True)
    nickname: str = Field(unique=True)


class UserCreate(UserBase):
    password: str


class User(UserBase, table=True):
    id: int | None = Field(default=None, primary_key=True)
    is_admin: bool = Field(default=False)
    password: str
    created_at: datetime = Field(default_factory=datetime.now)
    updated_at: datetime = Field(
        default_factory=datetime.now, sa_column_kwargs={"onupdate": datetime.now}
    )

    prompts: List["Prompt"] = Relationship(back_populates="owner")
    tags: List["Tag"] = Relationship(back_populates="owner")
    collections: List["Collection"] = Relationship(back_populates="user")


class TagBase(SQLModel):
    name: str = Field(unique=True)


class TagCreate(TagBase):
    pass


class PromptTagLink(SQLModel, table=True):
    prompt_id: Optional[int] = Field(
        default=None, foreign_key="prompt.id", primary_key=True
    )
    tag_id: Optional[int] = Field(default=None, foreign_key="tag.id", primary_key=True)


class Tag(TagBase, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    owner_id: Optional[int] = Field(default=None, foreign_key="user.id")
    created_at: datetime = Field(default_factory=datetime.now)
    updated_at: datetime = Field(
        default_factory=datetime.now, sa_column_kwargs={"onupdate": datetime.now}
    )

    owner: Optional[User] = Relationship(back_populates="tags")
    prompts: List["Prompt"] = Relationship(
        back_populates="tags", link_model=PromptTagLink
    )


class PromptBase(SQLModel):
    title: str
    content: str
    is_published: bool = Field(default=False)


class PromptCreate(PromptBase):
    tags: List[int] = []


class Prompt(PromptBase, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    likes: int = Field(default=0)
    owner_id: int = Field(foreign_key="user.id")
    created_at: datetime = Field(default_factory=datetime.now)
    updated_at: datetime = Field(
        default_factory=datetime.now, sa_column_kwargs={"onupdate": datetime.now}
    )

    owner: User = Relationship(back_populates="prompts")
    tags: List[Tag] = Relationship(back_populates="prompts", link_model=PromptTagLink)
    collections: List["Collection"] = Relationship(back_populates="prompt")


class CollectionBase(SQLModel):
    prompt_id: int = Field(foreign_key="prompt.id")


class Collection(CollectionBase, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    user_id: int = Field(foreign_key="user.id")
    created_at: datetime = Field(default_factory=datetime.now)

    user: User = Relationship(back_populates="collections")
    prompt: Prompt = Relationship(back_populates="collections")


class Query(BaseModel):
    page: int = 1
    limit: int = 10
    count: int = 0
    results: List[SQLModel] = []


class Response(BaseModel):
    success: bool = True
    msg: str | None = None
    query: Query | None = None
    record: SQLModel | None = None
    errors: dict[str, list[str]] | None = None


class TokenResponse(Response):
    access_token: str


class TokenData(BaseModel):
    user_id: int
